package com.aboverock.module.system.web;

import com.aboverock.common.domain.Result;
import com.aboverock.common.enums.LimitOperationEnum;
import com.aboverock.common.enums.MessageSourceKey;
import com.aboverock.core.spring.web.StringIdBaseController;
import com.aboverock.module.shiro.util.ShiroCacheUtil;
import com.aboverock.module.system.domain.Resource;
import com.aboverock.module.system.domain.Role;
import com.aboverock.module.system.domain.RoleResource;
import com.aboverock.module.system.domain.User;
import com.aboverock.module.system.domain.UserRole;
import com.aboverock.module.system.service.RoleResourceService;
import com.aboverock.module.system.service.RoleService;
import com.aboverock.module.system.service.UserRoleService;
import io.swagger.annotations.ApiOperation;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Rock Wang
 * @since 2018-07-26
 */
@RestController
@RequestMapping("system/role")
public class RoleController extends StringIdBaseController<Role> {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleResourceService roleResourceService;

    /**
     * Gets the roles.
     *
     * @return the roles
     */
    @ApiOperation(value = "获取所有角色")
    @Override
    public Result all(HttpServletRequest request) {
        return Result.success(roleService.getRoles());
    }

    @ApiOperation(value = "新增角色")
    @Override
    public Result save(@Validated @RequestBody Role role) {
        if (roleService.isDuplicatedCode(role)) {
            return Result.fail(MessageSourceKey.Common.COMMON_CODE_EXISTED);
        }

        return super.save(role);
    }

    @ApiOperation(value = "更新角色")
    @Override
    public Result update(@PathVariable("id") String id, @Validated @RequestBody Role role) {
        Role oldEntity = roleService.getById(id);
        if (null == oldEntity) {
            return Result.fail(MessageSourceKey.Common.COMMON_DATA_NOT_FOUND_KEY);
        }

        if (LimitOperationEnum.UPDATE_CODE_AND_DELETE_REFUSED.getValue().equals(oldEntity.getLimitOperation())
                && !role.getCode().equals(oldEntity.getCode())) {
            return Result.fail(MessageSourceKey.Common.COMMON_CODE_FIXED);
        }

        role.setId(id);
        if (roleService.isDuplicatedCode(role)) {
            return Result.fail(MessageSourceKey.Common.COMMON_CODE_EXISTED);
        }

        if (roleService.updateById(role)) {
            return Result.success(role);
        }

        return Result.fail();
    }

    @ApiOperation(value = "删除角色")
    @Override
    public Result delete(@PathVariable("id") String id) {
        Role role = roleService.getById(id);
        if (role != null && !LimitOperationEnum.NORMAL.getValue().equals(role.getLimitOperation())) {
            return Result.fail(MessageSourceKey.Common.COMMON_DATA_DELETE_REFUSE_KEY);
        }

        try {
            roleService.deleteById(id);
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        } catch (SQLException e) {
            logger.warn("Data-Smart：删除角色失败", e);
        }
        return Result.fail();
    }

    /**
     * Gets the users.
     *
     * @param roleId the role id
     * @return the users
     */
    @ApiOperation(value = "获取指定角色的所有用户")
    @GetMapping("{roleId}/users")
    public Result getUsers(@PathVariable String roleId) {
        List<User> users = roleService.getUsersByRoleId(roleId);
        return Result.success(users);
    }

    /**
     * Adds the users.
     *
     * @param roleId the role id
     * @param users the users
     * @return the result
     */
    @ApiOperation(value = "指定角色增加多个用户")
    @PostMapping("{roleId}/users")
    public Result addUsers(@PathVariable String roleId, @RequestBody List<User> users) {
        List<UserRole> userRoles = new ArrayList<UserRole>(users.size());
        for (User user : users) {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(user.getId());
            userRoles.add(userRole);
        }

        if (userRoleService.saveBatch(userRoles)) {
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        }

        return Result.fail();
    }

    /**
     * 删除指定角色下的多个用户.
     *
     * @param roleId the role id
     * @param users the users
     * @return the result
     */
    @ApiOperation(value = "指定角色删除多个用户")
    @DeleteMapping("{roleId}/users")
    public Result removeUsers(@PathVariable String roleId, @RequestBody List<User> users) {
        List<String> userIds = new ArrayList<String>(users.size());
        users.forEach(user -> userIds.add(user.getId()));

        if (userRoleService.removeByRoleIdAndUserIds(roleId, userIds)) {
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        }

        return Result.fail();
    }

    /**
     * Gets the resources.
     *
     * @param roleId the role id
     * @return the resources
     */
    @ApiOperation(value = "获取指定角色的所有资源")
    @GetMapping("{roleId}/resources")
    public Result getResources(@PathVariable String roleId) {
        List<Resource> resources = roleService.getResourcesByRoleId(roleId);
        return Result.success(resources);
    }

    /**
     * Adds the resources.
     *
     * @param roleId the role id
     * @param resources the resources
     * @return the result
     */
    @ApiOperation(value = "指定角色增加多个资源")
    @PostMapping("{roleId}/resources")
    public Result addResources(@PathVariable String roleId, @RequestBody List<Resource> resources) {
        List<RoleResource> roleResources = new ArrayList<RoleResource>(resources.size());
        for (Resource resource : resources) {
            RoleResource roleResource = new RoleResource();
            roleResource.setRoleId(roleId);
            roleResource.setResourceId(resource.getId());
            roleResources.add(roleResource);
        }

        if (roleResourceService.saveBatch(roleResources)) {
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        }

        return Result.fail();
    }

    /**
     * 删除指定角色下的多个资源.
     *
     * @param roleId the role id
     * @param resources the resources
     * @return the result
     */
    @ApiOperation(value = "删除指定角色下的多个资源")
    @DeleteMapping("{roleId}/resources")
    public Result removeResources(@PathVariable String roleId, @RequestBody List<Resource> resources) {
        List<String> resourceIds = new ArrayList<String>(resources.size());
        resources.forEach(resource -> resourceIds.add(resource.getId()));

        if (roleResourceService.removeByRoleIdAndResourceIds(roleId, resourceIds)) {
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        }

        return Result.fail();
    }

}
